package serviceImpl;

import javax.el.ELContext;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import model.GenericModel;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import service.GenericService;

public abstract class GenericServiceImpl<T extends GenericModel> implements
		GenericService<T>, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -361511070910067264L;

	

	public EntityManager getEm() {
		ELContext el = FacesContext.getCurrentInstance().getELContext();
		return (EntityManager) FacesContext.getCurrentInstance()
				.getApplication().getELResolver()
				.getValue(el, null, "entityManager");
	}

	private Class<T> classe;
	private Query query;

	@SuppressWarnings("unchecked")
	public GenericServiceImpl() {
		EntityManager em = JPAUtil.getEntityManager();
		classe = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		
	}

	public void salvar(T object) {
		if (object.getCodigo() != null) {
			getEm().merge(object);
		} else {
			getEm().persist(object);
		}
	}
	
	public T findOne(Long codigo) {
		return getEm().find(classe, codigo);
	}


	@SuppressWarnings("unchecked")
	public List<T> findAll(Long codigo) {
		query = getEm().createQuery(
				"Select c from " + classe.getName()
						+ " c where c.usuario.codigo = :codigo");
		query.setParameter("codigo", codigo);
		return query.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findAllByNome(Long codigo) {
		query = getEm().createQuery(
				"Select c from " + classe.getName()
						+ " c where c.usuario.codigo = :codigo group by c.nome");
		query.setParameter("codigo", codigo);
		return query.getResultList();
	}

	public void remover(T object) {
		try{
		T objectRemove = getEm().getReference(getClasse(), object.getCodigo());
		getEm().remove(objectRemove);
		getEm().flush();
		}catch(Exception e) {
			System.out.println("erro");
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao Excluir", "Erro ao excluir registro"));
		}
		
	}

	public Class<T> getClasse() {
		return classe;
	}

	public void setClasse(Class<T> classe) {
		this.classe = classe;
	}

}
